/*
 * Creep - the enemy
 *
 * Copyright 2008 James W. Hofmann
 *
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */

package rules;

class Creep
{

	inline public static var basehealth = 100; 
	inline public static var waveincrement = 10;

	inline public static var transitioninpct = 0.33;
	inline public static var transitionoutpct = 0.66;
	inline public static var perframemovement = 0.1;

	public var id : Int;

	public var wave : Wave;

	public var wavepathpos : Int;

	public var x : Int;
	public var y : Int;
	public var destx : Int;
	public var desty : Int;
	public var travelpct : Float;
	
	public var health : Int;
	public var maxhealth : Int;

	public var madetransition : Bool;

	public function new(spawnloc : Int, wave : Wave)
	{
		this.health = basehealth+(waveincrement*(wave.num-1)); 
		this.maxhealth = basehealth+(waveincrement*(wave.num-1)); 
		this.wave = wave;

		madetransition = false;

		wavepathpos = wave.path.length-1;

		var creeps = RulesAPI.g.creeps;
		this.id = creeps.setnext(this);

		x = GameMap.corners[spawnloc][0];
		y = GameMap.corners[spawnloc][1];
		
		var curt = RulesAPI.g.m.tiles[x][y];
		travelpct = 0;
		
		curt.creeps.push(this);
		movedecision();
				
		GameResponse.addcomposition(
		new GameResponse(GameResponse.msg_creepadd, [this.id, 
		this])
		);
		
	}

	public function hurt(qty : Int)
	{
		health-=qty;
		GameResponse.addcomposition(
		new GameResponse(GameResponse.msg_creephurt, [this, health])
		);
		if (health<=0)
			kill();
	}

	public function kill()
	{
		RulesAPI.g.creeps.remove(this.id);

		RulesAPI.g.m.tiles[x][y].creeps.remove(this);
		RulesAPI.g.m.tiles[destx][desty].creeps.remove(this);

		wave.count-=1;

		GameResponse.addcomposition(
		new GameResponse(GameResponse.msg_creepkill, this)
		);
	}

	public function up()
	{
		if (!(wavepathpos<=0 && travelpct>=1)) 
			// this condition means don't move, don't do anything.
		    // the game is over cause you toasted the
		    // base and stand on top of its remains. You creep you.
		{
			var cur = RulesAPI.g.m.tiles[x][y];
			var nearbyforts : List<GameTile> = 
			Lambda.filter(cur.neighbors, function(i : GameTile) 
			{return (i.fort != null);} 
			);	
			if (RulesAPI.g.m.tiles[destx][desty].terrain!=
				GameTile.ter_space // if we are going onto ground next
			    
				&& nearbyforts.length>0)
				attack(nearbyforts);
			else
				movement();
		}
		else
		{
			travelpct = 1;
			madetransition = false;
		}
	}

	inline public function attack(nearbyforts : List<GameTile>)
	{
		nearbyforts.first().fort.hurt(10);
	}

	inline public function movement()
	{
		if (travelpct>=1)
		{
			travelpct-=1;
			x = destx;
			y = desty;
			movedecision();
		}
		// when creeps travel they experience a transition stage
		// in which they are in both source and destination at
		// the same time. transitionin and transitionout control
		// the period during which this occurs. out should be
		// greater than in.
		else if (travelpct>=transitionoutpct)
		{
			RulesAPI.g.m.tiles[x][y].creeps.remove(this);
			madetransition = false;
		}
		else if (travelpct>=transitioninpct && !madetransition)
		{
			RulesAPI.g.m.tiles[destx][desty].creeps.push(this);				
			madetransition = true;
		}
		travelpct += perframemovement;
		GameResponse.addcomposition(
		new GameResponse(GameResponse.msg_creepmove, 
			[this, travelpct])
		);		
		// note that if perframemovement does not multiply to 1,
		// then there will be "overmovement" as travelpct will overflow
		// before being reset. Account for this in the client.
	}

	inline public function movedecision()
	{
		if (wavepathpos>0)
		{
			wavepathpos-=1;
			var next = wave.path[wavepathpos];
			destx = next.x;
			desty = next.y;
		}
	}

	public static function killfromplacement(x : Int, y : Int)
	{
		for (c in RulesAPI.g.creeps)
		{
			if ((c.destx == x && c.desty == y) ||
				(c.x == x && c.y == y))
			{
				c.kill();
			}
		}
	}

}
